import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Button, Tab, Balloon, Menu, Dropdown, Tag, Divider, Badge } from '@teamix/ui';
import Pagination from 'components/commonPagination';
import {
  Header,
  Body,
  BodyContent,
  OperationBar,
  Content,
  SearchIcon,
  YunxiaoIcon,
  ButtonIcon,
  Title,
} from '@alife/devops-ui';
import { ENUM, ORGANIZATION_ADMIN_ROLES, GROUP_ADMIN_ROLES } from 'utils/constants.js';
import utils from 'utils/index';
import { navigate } from 'utils/router';
import List from 'components/groupList';
import TextAvatar from '@txdfe/at-text-avatar';
import GroupSkeleton from 'components/skeleton/orgGroup';
import ListEmpty from 'atComponents/ListEmpty';
import MemberList from 'components/memberList';
import CreateGroupModal from 'components/createGroupModal';
import { access } from 'components/accessContainer/util';
import * as actions from '../actions/index';
import debounce from 'lodash.debounce';
import track, { enterPage, Perf } from 'utils/track';
import KEYCODE from 'utils/keycode';
import intl from '../../../../../../../locale';
const { user_role } = window.FORCE.organization;

const { Tooltip } = Balloon;

const { visibility_levels } = ENUM;
const { ctrlKey, ctrlTxt } = ENUM.getOSKeyMap();

class Root extends Component {
  static propTypes = {
    groupList: PropTypes.arrayOf(PropTypes.object),
    currentPage: PropTypes.number,
    total: PropTypes.number,
    order_by: PropTypes.string,
    navKey: PropTypes.string,
  };

  static defaultProps = {
    groupList: null,
    currentPage: 1,
    total: 0,
    order_by: 'updated_at',
    navKey: '',
  };

  constructor(props) {
    super(props);
    this.state = {
      membersDialogVisible: false,
      membersDialogGroup: {},
      createModalShow: false,
      pageSize: 10,
    };

    this.onSearch = debounce(this.onSearch, 500);
    window.T1 = new Date();
  }

  componentDidMount() {
    const navKey = utils.getUrlSearchParam('navKey') || 'mine';
    this.props.setNavKey(navKey);
    this.props.getGroupsCount();
    this.props.getGroupSettingData();
    document.addEventListener('keydown', this.handleKeyCodeEvent);
    enterPage(navKey === 'mine' ? 'Organization-Groups-Mine' : 'Organization-Groups-All', {
      sendPerf: false,
    });
  }

  handleKeyCodeEvent = (e) => {
    // ctrl + / 进行搜索
    if (e[ctrlKey] && e.keyCode === KEYCODE.SPLIT) {
      document.querySelector('.search-ctrl>button').click();
      document.querySelector('.search-ctrl input').focus();
    }
  };

  componentDidUpdate(prevProps) {
    if (this.props.location.search !== prevProps.location.search) {
      const navKey = utils.getUrlSearchParam('navKey') || 'mine';
      this.props.setNavKey(navKey);
      const { pageSize } = this.state;
      if (this.props.search) {
        this.props.getGroupsCount(pageSize);
      } else {
        this.props.getGroups(1, pageSize);
      }
    }
  }

  componentWillUnmount() {
    this.props.resetData();
    document.removeEventListener('keydown', this.handleKeyCodeEvent);
  }

  onPageChange = (value) => {
    const { pageSize } = this.state;
    this.props.getGroups(value, pageSize);
  };

  onPageSizeChange = (pageSize) => {
    this.setState(
      {
        pageSize,
      },
      () => {
        this.onPageChange(1);
      },
    );
  };

  filterLevel = (level) => {
    let label = '';
    visibility_levels.forEach((item) => {
      if (item.value === Number(level)) {
        label = item.label;
      }
    });
    return label;
  };

  handleExpand = (e, id, isExpanded) => {
    e.stopPropagation();
    e.preventDefault();
    // 有搜索条件时，只展开收起，不处理subGroupMap
    if (this.props.search) {
      this.props.updateSubGroupMapWithSearch(id);
      return;
    }
    if (isExpanded) {
      // 展开后收起,数据清空
      this.props.updateSubGroupMap(id);
    } else {
      this.props.getSubGroups(id);
    }
  };

  getDataSource = (groupList) => {
    const { subGroupMap } = this.props;
    return groupList
      ? groupList.map((group) => {
          const subGroup = subGroupMap[group.id];
          const isLoading = subGroup && subGroup.isLoadingSubGroup;
          const isExpanded = subGroup && subGroup.isExpanded;
          // 是不是库
          const isProject = group.type === 'project';
          const leftTriangle = isLoading ? (
            <Button loading text />
          ) : (
            <ButtonIcon
              name={`trilateral-${isExpanded ? 'down' : 'right'}-fill`}
              text
              onClick={(e) => {
                e.stopPropagation();
                e.preventDefault();
                this.handleExpand(e, group.id, isExpanded);
              }}
            />
          );

          // 企业管理员或者组管理员
          const isAdmin =
            access(ORGANIZATION_ADMIN_ROLES, user_role) ||
            access(GROUP_ADMIN_ROLES, ENUM.access_level[group.access_level]);
          const isPersonalNamespace = group.type === 'PersonalNamespace';
          return {
            left: (
              <span style={{ display: 'flex', alignItems: 'center' }}>
                {!isProject && group.group_count ? leftTriangle : null}
                {isProject ? (
                  <span className={'code-project-btn ml32'}>
                    <YunxiaoIcon type="code-basement-line" />
                  </span>
                ) : (
                  <span className={`code-group-btn ${group.group_count ? '' : 'ml32'}`}>
                    <YunxiaoIcon type={'folder-line'} />
                  </span>
                )}

                <TextAvatar text={group.path.toUpperCase()} image={group.avatar_url} isCover />
              </span>
            ),

            body: {
              title: (
                <span
                  className="project-list-item-title one-line-ellipsis"
                  style={{ display: 'flex' }}
                >
                  <Title trigger={<span>{group.name}</span>} align="t">
                    <div>{group.name}</div>
                  </Title>
                  {group.demo_project ? (
                    <Tag className="demo-repo-tag">
                      {intl.get({
                        id: 'code-assets.groups.containers.root.SampleCodeLibrary',
                        defaultMessage: '示例代码库',
                      })}
                    </Tag>
                  ) : null}
                </span>
              ),

              description: [
                <span className="project-list-item-desc">
                  {group.description ? (
                    <React.Fragment>
                      <span className="project-list-item-desc-project-desc">
                        <Title trigger={<span>{group.description}</span>}>
                          <div>{group.description}</div>
                        </Title>
                      </span>
                      <span className="project-list-item-desc-divider">·</span>
                    </React.Fragment>
                  ) : null}
                  <span className="project-list-item-desc-time">
                    {`${intl.get({
                      id: 'code-assets.src.utils.locale.UpdatedOn',
                      defaultMessage: '更新于',
                    })}${utils.getBeautyTime(group.updated_at)}`}
                  </span>
                </span>,
              ],
            },

            middle: {
              items: isProject
                ? []
                : [
                  <Balloon.Tooltip
                    type="primary"
                    align="t"
                    trigger={
                      <div style={{ width: 60 }}>
                        <Button type="normal" text className="normal-color">
                          <YunxiaoIcon type="folder-line" /> {group.group_count}
                        </Button>
                      </div>
                      }
                  >
                    {intl.get({
                        id: 'code-assets.groups.containers.root.SubcodeGroup',
                        defaultMessage: '子代码组',
                      })}
                  </Balloon.Tooltip>,
                  <Balloon.Tooltip
                    type="primary"
                    align="t"
                    trigger={
                      <div style={{ width: 60 }}>
                        <Button type="normal" text className="normal-color">
                          <YunxiaoIcon type="code-basement-line" /> {group.project_count}
                        </Button>
                      </div>
                      }
                  >
                    {intl.get({
                        id: 'code-assets.groups.containers.root.CodeBase',
                        defaultMessage: '代码库',
                      })}
                  </Balloon.Tooltip>,
                  ],
            },

            right: {
              hoverItems: [
                !isPersonalNamespace && isAdmin ? (
                  <Balloon.Tooltip
                    type="primary"
                    align="t"
                    trigger={
                      <ButtonIcon
                        type="secondary"
                        style={{ color: 'gray' }}
                        name="add-members-line"
                        onClick={(e) => {
                          e.stopPropagation();
                          e.preventDefault();
                          this.setState({
                            membersDialogVisible: true,
                            membersDialogGroup: group,
                          });
                        }}
                      />
                    }
                  >
                    {intl.get({
                      id: 'code-assets.groups.containers.root.MemberManagement',
                      defaultMessage: '成员管理',
                    })}
                  </Balloon.Tooltip>
                ) : null,
                !isPersonalNamespace && isAdmin ? (
                  <Balloon.Tooltip
                    type="primary"
                    align="t"
                    trigger={
                      <ButtonIcon
                        type="secondary"
                        name="setting-line"
                        color="gray"
                        onClick={(e) => {
                          e.stopPropagation();
                          e.preventDefault();
                          // TODO a标签点击无效，待list组件修复
                          navigate(`/${group.path_with_namespace}/settings`);
                        }}
                      />
                    }
                  >
                    {intl.get({
                      id: 'code-assets.groups.containers.root.EnableSettings',
                      defaultMessage: '打开设置',
                    })}
                  </Balloon.Tooltip>
                ) : null,
              ],

              items: [<Tag size="small">{this.filterLevel(group.visibility_level)}</Tag>],

              style: {
                width: 100,
              },
            },
          };
        })
      : [];
  };

  renderMembersDialog = () => {
    const { membersDialogVisible: visible, membersDialogGroup: group } = this.state;

    return (
      <MemberList
        visible={visible}
        pathResourceId={group.id}
        pathResourceType="group"
        isAdmin
        parentId={group.parent_id}
        align="tr br"
        role={ENUM.access_level[group.access_level]}
        onClose={() => {
          this.setState({
            membersDialogVisible: false,
            // membersDialogGroup: {},
          });
        }}
      />
    );
  };

  onChangeTab = (key) => {
    this.props.setNavKey(key.split('=')[1]);
    navigate(key);
  };

  renderContent = () => {
    const { groupList, subGroupMap } = this.props;

    return (
      <div className="organization-content-list-wrapper">
        <List
          // dataSource={dataSource}
          // pagination={{
          //   onLoadMore: (page) => {
          //     this.props.getGroups(page);
          //   },
          //   hasMore,
          //   useWindow: false,
          //   getScrollParent: () => {
          //     return document.querySelector('#container');
          //   },
          // }}
          hasHoverItems
          getDataSource={this.getDataSource}
          groupList={groupList}
          subGroupMap={subGroupMap}
        />
      </div>
    );
  };

  handleSort = (keys) => {
    this.props.updateData({
      order_by: keys[0],
    });

    const { pageSize } = this.state;
    this.props.getGroups(1, pageSize);
  };

  getCreateGroupAccess = () => {
    const { group_creator_role } = this.props;
    return (
      access(ORGANIZATION_ADMIN_ROLES, user_role) ||
      group_creator_role.map((item) => ENUM.access_level[item]).includes(user_role)
    );
  };

  onSearch = (search) => {
    this.props.updateData({
      projects: [],
      currentPage: 1,
      isLoading: true,
      search,
    });

    const { pageSize } = this.state;
    this.props.getGroupsCount(pageSize);
  };

  renderPageHeader = () => {
    const { total, order_by, search } = this.props;
    const hasCreateGroupAccess = this.getCreateGroupAccess();
    const extra = (
      <>
        <SearchIcon
          direction="rtl"
          placeholder={intl.get({
            id: 'code-assets.groups.containers.root.SearchForCodeGroups',
            defaultMessage: '搜索代码组',
          })}
          onChange={(value) => {
            this.onSearch(value);
          }}
          triggerTooltipProps={{
            children: (
              <div>
                {intl.get({
                  id: 'code-assets.groups.containers.root.Search',
                  defaultMessage: '搜索',
                })}
                <br />
                {ctrlTxt} + /
              </div>
            ),
            align: 't',
          }}
          className="search-ctrl"
          defaultValue={this.props.search}
        />

        <Dropdown
          trigger={<ButtonIcon text type="secondary" name="sort-line" style={{ color: 'gray' }} />}
          triggerType="click"
          align="tr br"
        >
          <Menu onSelect={this.handleSort} selectMode="single" selectedKeys={order_by}>
            {/* <Menu.Item key="updated_at">我更新时间</Menu.Item> */}
            <Menu.Item key="updated_at">
              {intl.get({
                id: 'code-assets.groups.containers.root.UpdateTime',
                defaultMessage: '更新时间',
              })}
            </Menu.Item>
            <Menu.Item key="created_at">
              {intl.get({
                id: 'code-assets.groups.containers.root.Created',
                defaultMessage: '创建时间',
              })}
            </Menu.Item>
          </Menu>
        </Dropdown>
        <Divider direction="ver" />
        <span>
          {hasCreateGroupAccess ? (
            this.renderAddBtn()
          ) : (
            <Tooltip
              trigger={
                <Button type="primary" disabled text>
                  {intl.get({
                    id: 'code-assets.groups.containers.root.CreateAGroup',
                    defaultMessage: '新建组',
                  })}
                </Button>
              }
              align="t"
            >
              {intl.get({
                id: 'code-assets.groups.containers.root.CurrentlyTheEnterpriseHasEnabled',
                defaultMessage: '当前企业开启了创建组的权限管控，如有需要请联系企业管理员修改',
              })}
            </Tooltip>
          )}
        </span>
      </>
    );

    return (
      <Header
        title={intl.get({
          id: 'code-assets.groups.containers.root.CodeGroup',
          defaultMessage: '代码组',
        })}
        operation={total === 0 && !search ? null : extra}
      />
    );
  };

  openNewProjectModal = () => {
    this.setState({
      createModalShow: true,
    });

    track({
      action: 'new_group',
      page: this.props.navKey === 'mine' ? 'Organization-Groups-Mine' : 'Organization-Groups-All',
      type: this.props.total ? '' : 'empty list',
      control: '',
    });
  };

  renderAddBtn = (type = 'primary') => {
    return (
      <Button type={type} onClick={this.openNewProjectModal}>
        {intl.get({
          id: 'code-assets.groups.containers.root.CreateAGroup',
          defaultMessage: '新建组',
        })}
      </Button>
    );
  };

  closeModal = (type) => {
    this.setState({
      [type]: false,
    });
  };

  render() {
    const { isLoading, groupList, search, navKey, currentPage, total, totalMine, totalAll } =
      this.props;
    const { createModalShow } = this.state;
    // 从devops项目新建库，组选项中新建组，打开的页面会携带参数showCreateGroupModal=true
    const showCreateGroupModal = utils.getUrlSearchParam('showCreateGroupModal') || '';
    // 根据tab 获取数据
    const dataSource = this.getDataSource(groupList);
    const btns = [
      <Button type="primary" onClick={this.openNewProjectModal}>
        {intl.get({
          id: 'code-assets.groups.containers.root.CreateACodeGroup',
          defaultMessage: '新建代码组',
        })}
      </Button>,
    ];

    const hasCreateGroupAccess = this.getCreateGroupAccess();

    let content;
    if (isLoading) {
      content = <GroupSkeleton />;
    } else if (dataSource.length === 0) {
      if (search) {
        content = (
          <ListEmpty
            fullPage
            type="org"
            description="抱歉，未找到匹配结果"
            className="no-btns"
            imgType="search"
          />
        );
      } else {
        content = (
          <ListEmpty
            fullPage
            type="org"
            content={navKey === 'all' ? '暂无可查看的代码组' : '暂未参与代码组'}
            description="组下支持管理多个子组/库，支持按组维护成员权限，新建试试吧"
            image="none"
            btns={hasCreateGroupAccess ? btns : []}
          />
        );
      }
    } else {
      content = this.renderContent(dataSource);
    }

    return (
      <>
        {this.renderPageHeader()}
        <Body className="group-container-root">
          <BodyContent>
            <OperationBar>
              <Tab
                onChange={this.onChangeTab}
                activeKey={`/groups?navKey=${this.props.navKey ? this.props.navKey : 'mine'}`}
                animation={false}
              >
                <Tab.Item
                  title={
                    <span className="title-span-badge">
                      <span>
                        {intl.get({
                          id: 'code-assets.groups.containers.root.IParticipatedIn',
                          defaultMessage: '我参与的',
                        })}
                      </span>
                      <Badge count={totalMine} showZero overflowCount={null} />
                    </span>
                  }
                  key="/groups?navKey=mine"
                />
                {user_role !== 'ORG_EXTERNAL_MEMBER' ? (
                  <Tab.Item
                    title={
                      <span className="title-span-badge">
                        <span>
                          {intl.get({
                            id: 'code-assets.groups.containers.root.All',
                            defaultMessage: '全部',
                          })}
                        </span>
                        <Badge count={totalAll} showZero overflowCount={null} />
                      </span>
                    }
                    key="/groups?navKey=all"
                  />
                ) : null}
              </Tab>
            </OperationBar>
            <Content>{content}</Content>
            <Pagination
              current={currentPage}
              total={total}
              onChange={this.onPageChange}
              pageSize={this.state.pageSize}
              onPageSizeChange={this.onPageSizeChange}
            />
          </BodyContent>
        </Body>

        {!isLoading ? (
          <Perf page={navKey === 'mine' ? 'Organization-Groups-Mine' : 'Organization-Groups-All'} />
        ) : null}
        {this.renderMembersDialog()}
        {(showCreateGroupModal || createModalShow) && (
          <CreateGroupModal
            closeModal={() => {
              this.closeModal('createModalShow');
            }}
            isModalOpen={showCreateGroupModal || createModalShow}
          />
        )}
      </>
    );
  }
}

export default connect(
  (state) => state.organization.groups,
  (dispatch) => bindActionCreators(actions, dispatch),
)(Root);
